using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace DebugCompanion
{
	partial class ProgressDlg : Form
	{
		ProgressDlg()
		{
			InitializeComponent();
		}

		private static ProgressDlg _instance = null;
		static object _sync = new object();

		public static void Show(string caption, string text, MethodInvoker operation,
			MethodInvoker finished, MethodInvoker terminate)
		{
			ProgressDlg dlg = new ProgressDlg();
			lock (_sync)
			{
				if (_instance != null)
					throw new InvalidOperationException();
				dlg.CreateControl();
				dlg.Text = caption;
				dlg._textLabel.Text = text;
				dlg._textLogger.Clear();
				dlg.VisibleChanged += dlg_VisibleChanged;
				_finished = finished;
				_terminate = terminate;
				_instance = dlg;
			}
			operation.BeginInvoke(OnFinished, null);
			dlg.ShowDialog();
			dlg.Dispose();
			_instance = null;
		}

		private static MethodInvoker _terminate;
		private static MethodInvoker _finished;
		private static volatile bool _visible;

		static void dlg_VisibleChanged(object sender, EventArgs e)
		{
			_visible = ((Control)sender).Visible;
		}

		static void WaitForDialog()
		{
			while (_instance != null && !_visible)
			{
				Thread.Sleep(0);
			}
		}

		public static void Terminate()
		{
			lock (_sync)
			{
				if (_instance != null)
				{
					WaitForDialog();
					_instance.Invoke(new MethodInvoker(delegate() { _instance.Close(); }));
					_instance = null;
				}
			}
		}

		public static void AddLogMessage(string msg)
		{
			lock (_sync)
			{
				if (_instance != null)
				{
					WaitForDialog();
					_instance.Invoke(new MethodInvoker(delegate()
					{
						_instance._textLogger.Select(_instance._textLogger.Text.Length, 0);
						_instance._textLogger.SelectedText = msg;
						_instance._textLogger.Select(_instance._textLogger.Text.Length, 0);
						_instance._textLogger.ScrollToCaret();
					}));
				}
			}
		}

		public static void SetProgress(int min, int max, int cur)
		{
			lock (_sync)
			{
				if (_instance != null)
				{
					WaitForDialog();
					_instance.Invoke(new MethodInvoker(delegate()
					{
						_instance._progressBar.Minimum = min;
						_instance._progressBar.Maximum = max;
						_instance._progressBar.Value = cur;
					}));
				}
			}
		}

		static void OnFinished(IAsyncResult ar)
		{
			lock (_sync)
			{
				if (_instance != null)
				{
					WaitForDialog();
					_instance.Invoke(new MethodInvoker(delegate()
					{
						_instance._terminateBtn.Text = "OK";
					}));
				}
			}
			_finished();
		}

		private void _terminateBtn_Click(object sender, EventArgs e)
		{
			lock (_sync)
			{
				_terminate();
				_instance = null;
				Close();
			}
		}
	}
}